深入理解FBTFT 您所在的位置:网站首页 linux spi lcd双端显示 深入理解FBTFT

深入理解FBTFT

2024-01-11 23:39| 来源: 网络整理| 查看: 265

深入理解FBTFT--使用篇 文章背景文章目标正文材料:编辑Device添加Driver可能遇到的问题总结

文章背景

最近扣扣群里老是有人问fbtft该怎么用,为什么显示屏驱动不了,之前一直忙着学习Linux内核,国庆到了,该放假了(总结一波之前的学习成果了,顺便填坑),所以该系列是填坑系列。 链接: 挖坑处:FBTFT源码逻辑分析 没有看过的可以看一下,不看也没关系。总之虽然fbtft的代码年代久远已经停止维护被移在staging中,但是fbtft完全可以作为初学者第一个用于理解内核的模块。 那么在本系列中,将会以连载的形式(国庆期间),使用fbtft,向fbtft中加入自己的屏幕,以及复刻fbtft(改造fbtft)。

文章目标 成功使用fbtft点亮自己的屏幕(添加自己的屏幕)。复刻FBTFT(SPI,I2C,MIPI,模拟GPIO口接入的FBTFT ) 正文 材料:

编译平台:Win10 Wsl2(Ubuntu 20) 目标平台:全志H3 香橙派(Machine U-boot+Mainline Kernel+自己做的根文件系统) 以上相关教程,看我空间。 显示屏:ST7789 240*240 IPS屏。(淘宝中景园有卖) 少量杜邦线。 CH340USB转串口。

编辑Device

(先提一句:主线内核里是有fbtft的源码的,在编译内核时,fbtft模块已经被编译好了,不用到处找在哪,就在你跟文件系统里,源码就在你内核里。) 根据Linux统一设备模型思想:Device提供有什么用的硬件信息,Driver提供使用硬件信息的方法。 我们打开 /kernel/driver/staging/fbtft/fbtft_device.c文件

static struct fbtft_device_display displays[] = { { .name = "adafruit18", .spi = &(struct spi_board_info) { .modalias = "fb_st7735r", .max_speed_hz = 32000000, .mode = SPI_MODE_0, .platform_data = &(struct fbtft_platform_data) { .display = { .buswidth = 8, .backlight = 1, }, .gamma = ADAFRUIT18_GAMMA, } } }, { .name = "adafruit18_green", .spi = &(struct spi_board_info) { .modalias = "fb_st7735r", .max_speed_hz = 4000000, .mode = SPI_MODE_0, .platform_data = &(struct fbtft_platform_data) { .display = { .buswidth = 8, .backlight = 1, .fbtftops.set_addr_win = adafruit18_green_tab_set_addr_win, }, .bgr = true, .gamma = ADAFRUIT18_GAMMA, } } }, { ......................省略

该结构体就是描述了大量的显示屏信息,我们在最后面仿造前面的,加上

{ .name = "bosstft",//你自己取 .spi = &(struct spi_board_info) { .modalias = "fb_st7789s",//匹配显示屏的名字 .max_speed_hz = 96000000,//最大SPI速率 .mode = SPI_MODE_0,//spi的模式 .bus_num=0,//使用SPI0 .chip_select=0,//使用SPI0的CS0管脚 .platform_data = &(struct fbtft_platform_data) { .display = { .buswidth = 8, //8为总线 .backlight = 1, //有背光 }, .gpios = (const struct fbtft_gpio []) { { "reset", 20 },//reset占用的管脚号 { "dc", 10 },//dc占用的管脚号 { "led", 9 },//背光占用的管脚号 }, } } }

我都写注释了,不会还有人看不懂吧?这些变量的值可以自己根据实际情况添加,fbtft_device文件的修改完成。

添加Driver

接着我们修改位于统一设备模型中的driver 在/kernel/driver/staging/fbtft/新建文件st7789s.c 大概的步骤:

再次设置像素宽高提供显示屏初始化代码提供显示屏写入像素的代码。注册驱动 #include #include #include #include #include "fbtft.h" #define DRVNAME "fb_st7789s" #define WIDTH 240 #define HEIGHT 240 #define DEFAULT_GAMMA "1F 1A 18 0A 0F 06 45 87 32 0A 07 02 07 05 00\n" \ "00 25 27 05 10 09 3A 78 4D 05 18 0D 38 3A 1F" //GAMMA应该是用来矫正颜色的,专业人士懂的改,不懂的默认。 static int init_display(struct fbtft_par *par) {//显示屏驱动IC一般需要前面一段初始化程序,这个就是 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); par->fbtftops.reset(par);//显示屏初始化前先reset,防止存有之前的配置 write_reg(par, 0x11);//寄存器写入 mdelay(120); write_reg(par, 0x36,0x00); write_reg(par, 0x3A,0x05); write_reg(par, 0xB2,0x0C,0x0C,0x00,0x33,0x33); write_reg(par, 0xB7,0x35); write_reg(par, 0xBB,0x32); write_reg(par, 0xC2,0x01); write_reg(par, 0xC3,0x15); write_reg(par, 0xC4,0x20); write_reg(par, 0xC6,0x0F); write_reg(par, 0xD0,0xA4,0xA1); write_reg(par, 0xE0,0xD0,0x08,0x0E,0x09,0x09,0x05,0x31,0x33,0x48,0x17,0x14,0x15,0x31,0x34); write_reg(par, 0xE1,0xD0,0x08,0x0E,0x09,0x09,0x15,0x31,0x33,0x48,0x17,0x14,0x15,0x31,0x34); write_reg(par, 0x21); write_reg(par, 0x29); return 0; } static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) {//设置写的范围 fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); //打印必要信息 write_reg(par, 0x2A,(xs>>8)&(0xFF),xs&0xFF,(xe>>8)&(0xFF),xe&0xFF); write_reg(par, 0x2B,(ys>>8)&(0xFF),ys&0xFF,(ye>>8)&(0xFF),ye&0xFF); /* Memory write */ write_reg(par, 0x2C); } static struct fbtft_display display = { .regwidth = 8,//总线尾数 .width = WIDTH, //显示屏像素宽 .height = HEIGHT,//显示屏像素高 .gamma_num = 2,//默认 .gamma_len = 15,//默认 .gamma = DEFAULT_GAMMA,//默认 .fbtftops = { .init_display = init_display,//初始化回调函数 .set_addr_win = set_addr_win,//设置写入范围回调函数 }, }; FBTFT_REGISTER_DRIVER(DRVNAME, "boss,st7789s", &display);//注册驱动 MODULE_ALIAS("spi:" DRVNAME); MODULE_ALIAS("platform:" DRVNAME); MODULE_ALIAS("spi:st7789s"); MODULE_ALIAS("platform:st7789s"); MODULE_DESCRIPTION("FB driver for the ST7789S LCD display controller"); MODULE_AUTHOR("Boss"); MODULE_LICENSE("GPL");

说明write_reg(par, 0x36,0x00);是宏定义,第一个0x36是作为寄存器地址,此时DC线被拉低,第二个第三个等是数据,此时DC被拉高。 如果要移植其他显示屏,我们一般只需要重写init_display,和set_addr_win,分别对于初始化和设置写入范围。 好,弄完了!很有精神!现在开始编译。 编译完丢进根文件系统里。 然后输入:

modprobe fbtft_device name=bosstft busnum=0 cs=0 speed=50000000 debug=0

name:fbtft_device里你自己设置的 busnum:哪个SPI CS:哪个SPI的哪个CS片选线 speed:时钟速度(会自动往接近的频率设置,100000000实际应该为96000000,没测试过但是应该是这样) debug:数字越大,调试的时候打印的信息越多,我debug的时候设置为7.

现在FB应该挂上去了,启动桌面吧。

附图:

启动图片

可能遇到的问题

1.FB成功挂上去了,屏幕不亮或者乱闪。 小伙子,测测SPI数据线的电压,检查一下设备树里是否配置上拉。 2.模块挂不上去 modprobe检查依赖是依靠文件的,单独放新模块进去当然不行,得整个编译后的模块文件夹重新放进根文件系统,或者用kmod。 3.编译失败 啊这,留言吧。

总结

十一前晚有空写的,根据之前回忆写的,没有具体测试,应该能用,毕竟我的屏幕已经亮了,可能还有错误,遇到再改吧(反正一般人不会看到这篇的)。 使用篇比较水,确实没啥写的,FBTFT原理很简单(至少对我来说是),有问题留言就是了,之后会连载复刻篇 。

另外:屏幕240X240已经很清楚了,那如果是相同大小的400X400呢? 请期待另外一篇:《C端嵌入式显示屏痛点解决——低成本超高清嵌入式屏幕的调通》挖坑…



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有